/*
 * PhotonRTOS础光实时操作系统 -- 体系架构定时器实现
 *
 * Copyright (C) 2023 国科础石(重庆)软件有限公司
 *
 * 作者: Jiayuan Liang <liangjiayuan@kernelsoft.com>
 *
 * License terms: GNU General Public License (GPL) version 3
 *
 */
#include "Bsp/Bsp.h"
#include "IfxPort.h"
#include "IfxStm.h"
#include "printk.h"
#include "photon/irqflags.h"
#include <photon/irq.h>
#include <photon/time.h>
#include <autosar/counter_internal.h>
#include <asm/smp.h>
#include <photon/init_integrity.h>
#include <photon/sched.h>
#include <photon/smp_lock.h>
#include <autosar/internal.h>
#include <asm/arch_timer.h>
#include <autosar/internal.h>
#include <asm/timex.h>
/*********************************************************************************************************************/
/*-------------------------------------------------Global variables--------------------------------------------------*/
/*********************************************************************************************************************/
IfxStm_CompareConfig g_STMConf0;                                 /* STM configuration structure                      */
IfxStm_CompareConfig g_STMConf1;                                 /* STM configuration structure                      */

Ifx_TickTime g_ticksFor1ms;
Ifx_TickTime g_ticksFor10ms;

/*********************************************************************************************************************/
/*------------------------------------------------------Macros-------------------------------------------------------*/
/*********************************************************************************************************************/
#define TIMER_INT_TIME          1                             /* Time between interrupts in ms                    */

#define STM0                     &MODULE_STM0                    /* STM0 is used in this example                     */

#define STM1                     &MODULE_STM1                    /* STM0 is used in this example                     */

/**
 * 声明中断相关信息
 *
 */


/*********************************************************************************************************************/
/*---------------------------------------------Function Implementations----------------------------------------------*/
/*********************************************************************************************************************/
/* Macro to define Interrupt Service Routine.
 * This macro makes following definitions:
 * 1) Define linker section as .intvec_tc<vector number>_<interrupt priority>.
 * 2) define compiler specific attribute for the interrupt functions.
 * 3) define the Interrupt service routine as ISR function.
 *
 * IFX_INTERRUPT(isr, vectabNum, priority)
 *  - isr: Name of the ISR function.
 *  - vectabNum: Vector table number.
 *  - priority: Interrupt priority. Refer Usage of Interrupt Macro for more details.
 */
IFX_INTERRUPT(isrSTM_Core0, 0, ISR_PRIORITY_STM_CORE0);
void isrSTM_Core0(void)
{
	do_hard_irq(ISR_PRIORITY_STM_CORE0, NULL);
	return;
}

IFX_INTERRUPT(isrSTM_Core1, 1, ISR_PRIORITY_STM_CORE1);

void isrSTM_Core1(void)
{
	do_hard_irq(ISR_PRIORITY_STM_CORE1, NULL);
	return;
}
void isr_stm_core0_handle(void)
{
    /* Update the compare register value that will trigger the next interrupt and toggle the LED */
    Ifx_TickTime stmNow;

    add_jiffies_64(1);

	current->live_tick--;
	if (current->live_tick <= 0 && current->sched_policy == SCHED_TIMESLICE) {

		set_task_need_resched(current);
	}

    stmNow         = (Ifx_TickTime)IfxStm_get(STM0) & TIME_INFINITE;
    IncrementHardwareCounter(smp_processor_id());

    IfxStm_updateCompare(STM0, g_STMConf0.comparator, stmNow + g_ticksFor1ms);

}

void isr_stm_core1_handle(void)
{
	Ifx_TickTime stmNow;
    /* Update the compare register value that will trigger the next interrupt and toggle the LED */
    IncrementHardwareCounter(smp_processor_id());
	current->live_tick--;
	if (current->live_tick <= 0 && current->sched_policy == SCHED_TIMESLICE) {

		set_task_need_resched(current);
	}

	stmNow         = (Ifx_TickTime)IfxStm_get(STM1) & TIME_INFINITE;

	IfxStm_updateCompare(STM1, g_STMConf1.comparator, stmNow + g_ticksFor1ms);
}

DeclareInterrupt(isr_stm_core0_handle, ISR_PRIORITY_STM_CORE0, HWIRQ_TYPE_EDGE_RISING, 1000, ISR_PRIORITY_STM_CORE0, true);
DeclareInterrupt(isr_stm_core1_handle, ISR_PRIORITY_STM_CORE1, HWIRQ_TYPE_EDGE_RISING, 2000, ISR_PRIORITY_STM_CORE1, true);

struct irq_desc *os_irq_desc[NR_IRQS] = {
	[0] = &ISR_ATTR(isr_stm_core0_handle),
	[1] = &ISR_ATTR(isr_stm_core1_handle),
	NULL,
};


/* Function to initialize the STM */
void initSTM0(void)
{
    IfxStm_initCompareConfig(&g_STMConf0);           /* Initialize the configuration structure with default values   */

    g_STMConf0.triggerPriority = ISR_PRIORITY_STM_CORE0;   /* Set the priority of the interrupt                            */
    g_STMConf0.typeOfService = IfxSrc_Tos_cpu0;      /* Set the service provider for the interrupts                  */
    g_STMConf0.ticks = g_ticksFor1ms;              /* Set the number of ticks after which the timer triggers an
                                                     * interrupt for the first time                                 */
    IfxStm_initCompare(STM0, &g_STMConf0);            /* Initialize the STM with the user configuration               */
}

void initSTM1(void)
{

    IfxStm_initCompareConfig(&g_STMConf1);           /* Initialize the configuration structure with default values   */
    g_STMConf1.triggerPriority = ISR_PRIORITY_STM_CORE1;   /* Set the priority of the interrupt                            */
    g_STMConf1.typeOfService = IfxSrc_Tos_cpu1;      /* Set the service provider for the interrupts                  */
    g_STMConf1.ticks = g_ticksFor1ms;              /* Set the number of ticks after which the timer triggers an
     	 	 	 	 	 	 	 	 	 	 	 	 * interrupt for the first time                                 */
    IfxStm_initCompare(STM1, &g_STMConf1);            /* Initialize the STM with the user configuration               */
}

/*
 * @brief 定时器相关操作
 *
 */
static uint32_t arch_timer_rate;

static void
arch_timer_detect_rate(void)
{
	arch_timer_rate = arch_timer_get_cntfrq();

	pr_debug("频率为 %d\n",arch_timer_rate);
}

void init_time_arch(void);
void init_time_arch(void)
{
	arch_timer_detect_rate();
	g_ticksFor1ms = IfxStm_getTicksFromMilliseconds(BSP_DEFAULT_TIMER, TIMER_INT_TIME) * 1;
	initSTM0();
	initSTM1();
}

void arch_timer_secondary_init(void)
{

}

void init_timer_arch(void);
void init_timer_arch(void)
{
	MODULE_INIT(init_timer_arch);
}


int xilinx_ttc_int_status(int cpu, uint32_t countid)
{
	return 0;
}
